home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cdrtools-1.10 / libhfs_iso / low.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-03-05  |  12.3 KB  |  524 lines

  1. /*
  2.  * hfsutils - tools for reading and writing Macintosh HFS volumes
  3.  * Copyright (C) 1996, 1997 Robert Leslie
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. #include <mconfig.h>
  21. #include <strdefs.h>
  22. #include <stdxlib.h>
  23. #include <errno.h>
  24. #include <unixstd.h>
  25. #include <fcntl.h>
  26.  
  27. #include "internal.h"
  28. #include "data.h"
  29. #include "block.h"
  30. #include "low.h"
  31. #include "file.h"
  32.  
  33. /*
  34.  * NAME:    low->lockvol()
  35.  * DESCRIPTION:    prevent destructive simultaneous access
  36.  */
  37. int l_lockvol(vol)
  38.     hfsvol    *vol;
  39. {
  40. # ifndef NODEVLOCKS
  41.  
  42.   struct flock lock;
  43.  
  44.   lock.l_type   = (vol->flags & HFS_READONLY) ? F_RDLCK : F_WRLCK;
  45.   lock.l_start  = 0;
  46.   lock.l_whence = SEEK_SET;
  47.   lock.l_len    = 0;
  48.  
  49.   if (fcntl(vol->fd, F_SETLK, &lock) < 0)
  50.     {
  51.       ERROR(errno, "unable to obtain lock for device");
  52.       return -1;
  53.     }
  54.  
  55. # endif
  56.  
  57.   return 0;
  58. }
  59.  
  60. /*
  61.  * NAME:    low->readblock0()
  62.  * DESCRIPTION:    read the first sector and get bearings
  63.  */
  64. int l_readblock0(vol)
  65.     hfsvol    *vol;
  66. {
  67.   block b;
  68.   unsigned char *ptr = b;
  69.   Block0 rec;
  70.  
  71.   if (b_readlb(vol, 0, &b) < 0)
  72.     return -1;
  73.  
  74.   d_fetchw(&ptr, &rec.sbSig);
  75.   d_fetchw(&ptr, &rec.sbBlkSize);
  76.   d_fetchl(&ptr, &rec.sbBlkCount);
  77.   d_fetchw(&ptr, &rec.sbDevType);
  78.   d_fetchw(&ptr, &rec.sbDevId);
  79.   d_fetchl(&ptr, &rec.sbData);
  80.   d_fetchw(&ptr, &rec.sbDrvrCount);
  81.   d_fetchl(&ptr, &rec.ddBlock);
  82.   d_fetchw(&ptr, &rec.ddSize);
  83.   d_fetchw(&ptr, &rec.ddType);
  84.  
  85.   switch (rec.sbSig)
  86.     {
  87.     case 0x4552:  /* block device with a partition table */
  88.       {
  89.     if (rec.sbBlkSize != HFS_BLOCKSZ)
  90.       {
  91.         ERROR(EINVAL, "unsupported block size");
  92.         return -1;
  93.       }
  94.  
  95.     vol->vlen = rec.sbBlkCount;
  96.  
  97.     if (l_readpm(vol) < 0)
  98.       return -1;
  99.       }
  100.       break;
  101.  
  102.     case 0x4c4b:  /* bootable floppy */
  103.       vol->pnum = 0;
  104.       break;
  105.  
  106.     default:  /* non-bootable floppy or something else */
  107.  
  108.       /* some miscreant media may also be partitioned;
  109.      we attempt to read a partition map, but ignore any failure */
  110.  
  111.       if (l_readpm(vol) < 0)
  112.     vol->pnum = 0;
  113.     }
  114.  
  115.   return 0;
  116. }
  117.  
  118. /*
  119.  * NAME:    low->readpm()
  120.  * DESCRIPTION:    read the partition map and locate an HFS volume
  121.  */
  122. int l_readpm(vol)
  123.     hfsvol    *vol;
  124. {
  125.   block b;
  126.   unsigned char *ptr;
  127.   Partition map;
  128.   unsigned long bnum;
  129.   int pnum;
  130.  
  131.   bnum = 1;
  132.   pnum = vol->pnum;
  133.  
  134.   while (1)
  135.     {
  136.       if (b_readlb(vol, bnum, &b) < 0)
  137.     return -1;
  138.  
  139.       ptr = b;
  140.  
  141.       d_fetchw(&ptr, &map.pmSig);
  142.       d_fetchw(&ptr, &map.pmSigPad);
  143.       d_fetchl(&ptr, &map.pmMapBlkCnt);
  144.       d_fetchl(&ptr, &map.pmPyPartStart);
  145.       d_fetchl(&ptr, &map.pmPartBlkCnt);
  146.  
  147.       memcpy(map.pmPartName, ptr, 32);
  148.       map.pmPartName[32] = 0;
  149.       ptr += 32;
  150.  
  151.       memcpy(map.pmParType, ptr, 32);
  152.       map.pmParType[32] = 0;
  153.       ptr += 32;
  154.  
  155.       d_fetchl(&ptr, &map.pmLgDataStart);
  156.       d_fetchl(&ptr, &map.pmDataCnt);
  157.       d_fetchl(&ptr, &map.pmPartStatus);
  158.       d_fetchl(&ptr, &map.pmLgBootStart);
  159.       d_fetchl(&ptr, &map.pmBootSize);
  160.       d_fetchl(&ptr, &map.pmBootAddr);
  161.       d_fetchl(&ptr, &map.pmBootAddr2);
  162.       d_fetchl(&ptr, &map.pmBootEntry);
  163.       d_fetchl(&ptr, &map.pmBootEntry2);
  164.       d_fetchl(&ptr, &map.pmBootCksum);
  165.  
  166.       memcpy(map.pmProcessor, ptr, 16);
  167.       map.pmProcessor[16] = 0;
  168.       ptr += 16;
  169.  
  170.       if (map.pmSig == 0x5453)
  171.     {
  172.       /* old partition map sig */
  173.  
  174.       ERROR(EINVAL, "unsupported partition map signature");
  175.       return -1;
  176.     }
  177.  
  178.       if (map.pmSig != 0x504d)
  179.     {
  180.       ERROR(EINVAL, "bad partition map");
  181.       return -1;
  182.     }
  183.  
  184.       if (strcmp((char *) map.pmParType, "Apple_HFS") == 0 && --pnum == 0)
  185.     {
  186.       if (map.pmLgDataStart != 0)
  187.         {
  188.           ERROR(EINVAL, "unsupported start of partition logical data");
  189.           return -1;
  190.         }
  191.  
  192.       vol->vstart = map.pmPyPartStart;
  193.       vol->vlen   = map.pmPartBlkCnt;
  194.  
  195.       return 0;
  196.     }
  197.  
  198.       if (bnum >= map.pmMapBlkCnt)
  199.     {
  200.       ERROR(EINVAL, "can't find HFS partition");
  201.       return -1;
  202.     }
  203.  
  204.       ++bnum;
  205.     }
  206. }
  207.  
  208. /*
  209.  * NAME:    low->readmdb()
  210.  * DESCRIPTION:    read the master directory block into memory
  211.  */
  212. int l_readmdb(vol)
  213.     hfsvol    *vol;
  214. {
  215.   block b;
  216.   unsigned char *ptr = b;
  217.   MDB *mdb = &vol->mdb;
  218.   hfsfile *ext = &vol->ext.f;
  219.   hfsfile *cat = &vol->cat.f;
  220.   int i;
  221.  
  222.   if (b_readlb(vol, 2, &b) < 0)
  223.     return -1;
  224.  
  225.   d_fetchw(&ptr, &mdb->drSigWord);
  226.   d_fetchl(&ptr, &mdb->drCrDate);
  227.   d_fetchl(&ptr, &mdb->drLsMod);
  228.   d_fetchw(&ptr, &mdb->drAtrb);
  229.   d_fetchw(&ptr, (short *) &mdb->drNmFls);
  230.   d_fetchw(&ptr, (short *) &mdb->drVBMSt);
  231.   d_fetchw(&ptr, (short *) &mdb->drAllocPtr);
  232.   d_fetchw(&ptr, (short *) &mdb->drNmAlBlks);
  233.   d_fetchl(&ptr, (long *) &mdb->drAlBlkSiz);
  234.   d_fetchl(&ptr, (long *) &mdb->drClpSiz);
  235.   d_fetchw(&ptr, (short *) &mdb->drAlBlSt);
  236.   d_fetchl(&ptr, &mdb->drNxtCNID);
  237.   d_fetchw(&ptr, (short *) &mdb->drFreeBks);
  238.  
  239.   d_fetchs(&ptr, mdb->drVN, sizeof(mdb->drVN));
  240.  
  241.   if (ptr - b != 64)
  242.     abort();
  243.  
  244.   d_fetchl(&ptr, &mdb->drVolBkUp);
  245.   d_fetchw(&ptr, &mdb->drVSeqNum);
  246.   d_fetchl(&ptr, (long *) &mdb->drWrCnt);
  247.   d_fetchl(&ptr, (long *) &mdb->drXTClpSiz);
  248.   d_fetchl(&ptr, (long *) &mdb->drCTClpSiz);
  249.   d_fetchw(&ptr, (short *) &mdb->drNmRtDirs);
  250.   d_fetchl(&ptr, (long *) &mdb->drFilCnt);
  251.   d_fetchl(&ptr, (long *) &mdb->drDirCnt);
  252.  
  253.   for (i = 0; i < 8; ++i)
  254.     d_fetchl(&ptr, &mdb->drFndrInfo[i]);
  255.  
  256.   if (ptr - b != 124)
  257.     abort();
  258.  
  259.   d_fetchw(&ptr, (short *) &mdb->drVCSize);
  260.   d_fetchw(&ptr, (short *) &mdb->drVBMCSize);
  261.   d_fetchw(&ptr, (short *) &mdb->drCtlCSize);
  262.  
  263.   d_fetchl(&ptr, (long *) &mdb->drXTFlSize);
  264.  
  265.   for (i = 0; i < 3; ++i)
  266.     {
  267.       d_fetchw(&ptr, (short *) &mdb->drXTExtRec[i].xdrStABN);
  268.       d_fetchw(&ptr, (short *) &mdb->drXTExtRec[i].xdrNumABlks);
  269.     }
  270.  
  271.   if (ptr - b != 146)
  272.     abort();
  273.  
  274.   d_fetchl(&ptr, (long *) &mdb->drCTFlSize);
  275.  
  276.   for (i = 0; i < 3; ++i)
  277.     {
  278.       d_fetchw(&ptr, (short *) &mdb->drCTExtRec[i].xdrStABN);
  279.       d_fetchw(&ptr, (short *) &mdb->drCTExtRec[i].xdrNumABlks);
  280.     }
  281.  
  282.   if (ptr - b != 162)
  283.     abort();
  284.  
  285.   vol->lpa = mdb->drAlBlkSiz / HFS_BLOCKSZ;
  286.  
  287.   /* extents pseudo-file structs */
  288.  
  289.   ext->vol   = vol;
  290.   ext->parid = 0;
  291.   strcpy(ext->name, "extents overflow");
  292.  
  293.   ext->cat.cdrType          = cdrFilRec;
  294.   /* ext->cat.cdrResrv2 */
  295.   ext->cat.u.fil.filFlags   = 0;
  296.   ext->cat.u.fil.filTyp     = 0;
  297.   /* ext->cat.u.fil.filUsrWds */
  298.   ext->cat.u.fil.filFlNum   = HFS_CNID_EXT;
  299.   ext->cat.u.fil.filStBlk   = mdb->drXTExtRec[0].xdrStABN;
  300.   ext->cat.u.fil.filLgLen   = mdb->drXTFlSize;
  301.   ext->cat.u.fil.filPyLen   = mdb->drXTFlSize;
  302.   ext->cat.u.fil.filRStBlk  = 0;
  303.   ext->cat.u.fil.filRLgLen  = 0;
  304.   ext->cat.u.fil.filRPyLen  = 0;
  305.   ext->cat.u.fil.filCrDat   = mdb->drCrDate;
  306.   ext->cat.u.fil.filMdDat   = mdb->drLsMod;
  307.   ext->cat.u.fil.filBkDat   = 0;
  308.   /* ext->cat.u.fil.filFndrInfo */
  309.   ext->cat.u.fil.filClpSize = 0;
  310.  
  311.   memcpy(ext->cat.u.fil.filExtRec, mdb->drXTExtRec, sizeof(ExtDataRec));
  312.   for (i = 0; i < 3; ++i)
  313.     {
  314.       ext->cat.u.fil.filRExtRec[i].xdrStABN    = 0;
  315.       ext->cat.u.fil.filRExtRec[i].xdrNumABlks = 0;
  316.     }
  317.   f_selectfork(ext, 0);
  318.  
  319.   ext->clump = mdb->drXTClpSiz;
  320.   ext->flags = 0;
  321.  
  322.   ext->prev = ext->next = 0;
  323.  
  324.   /* catalog pseudo-file structs */
  325.  
  326.   cat->vol   = vol;
  327.   cat->parid = 0;
  328.   strcpy(cat->name, "catalog");
  329.  
  330.   cat->cat.cdrType          = cdrFilRec;
  331.   /* cat->cat.cdrResrv2 */
  332.   cat->cat.u.fil.filFlags   = 0;
  333.   cat->cat.u.fil.filTyp     = 0;
  334.   /* cat->cat.u.fil.filUsrWds */
  335.   cat->cat.u.fil.filFlNum   = HFS_CNID_CAT;
  336.   cat->cat.u.fil.filStBlk   = mdb->drCTExtRec[0].xdrStABN;
  337.   cat->cat.u.fil.filLgLen   = mdb->drCTFlSize;
  338.   cat->cat.u.fil.filPyLen   = mdb->drCTFlSize;
  339.   cat->cat.u.fil.filRStBlk  = 0;
  340.   cat->cat.u.fil.filRLgLen  = 0;
  341.   cat->cat.u.fil.filRPyLen  = 0;
  342.   cat->cat.u.fil.filCrDat   = mdb->drCrDate;
  343.   cat->cat.u.fil.filMdDat   = mdb->drLsMod;
  344.   cat->cat.u.fil.filBkDat   = 0;
  345.   /* cat->cat.u.fil.filFndrInfo */
  346.   cat->cat.u.fil.filClpSize = 0;
  347.  
  348.   memcpy(cat->cat.u.fil.filExtRec, mdb->drCTExtRec, sizeof(ExtDataRec));
  349.   for (i = 0; i < 3; ++i)
  350.     {
  351.       cat->cat.u.fil.filRExtRec[i].xdrStABN    = 0;
  352.       cat->cat.u.fil.filRExtRec[i].xdrNumABlks = 0;
  353.     }
  354.   f_selectfork(cat, 0);
  355.  
  356.   cat->clump = mdb->drCTClpSiz;
  357.   cat->flags = 0;
  358.  
  359.   cat->prev = cat->next = 0;
  360.  
  361.   return 0;
  362. }
  363.  
  364. /*
  365.  * NAME:    low->writemdb()
  366.  * DESCRIPTION:    write the master directory block to disk
  367.  */
  368. int l_writemdb(vol)
  369.     hfsvol    *vol;
  370. {
  371.   block b;
  372.   unsigned char *ptr = b;
  373.   MDB *mdb = &vol->mdb;
  374.   hfsfile *ext = &vol->ext.f;
  375.   hfsfile *cat = &vol->cat.f;
  376.   int i;
  377.  
  378.   memset(&b, 0, sizeof(b));
  379.  
  380.   mdb->drXTFlSize = ext->cat.u.fil.filPyLen;
  381.   mdb->drXTClpSiz = ext->clump;
  382.   memcpy(mdb->drXTExtRec, ext->cat.u.fil.filExtRec, sizeof(ExtDataRec));
  383.  
  384.   mdb->drCTFlSize = cat->cat.u.fil.filPyLen;
  385.   mdb->drCTClpSiz = cat->clump;
  386.   memcpy(mdb->drCTExtRec, cat->cat.u.fil.filExtRec, sizeof(ExtDataRec));
  387.  
  388.   d_storew(&ptr, mdb->drSigWord);
  389.   d_storel(&ptr, mdb->drCrDate);
  390.   d_storel(&ptr, mdb->drLsMod);
  391.   d_storew(&ptr, mdb->drAtrb);
  392.   d_storew(&ptr, mdb->drNmFls);
  393.   d_storew(&ptr, mdb->drVBMSt);
  394.   d_storew(&ptr, mdb->drAllocPtr);
  395.   d_storew(&ptr, mdb->drNmAlBlks);
  396.   d_storel(&ptr, mdb->drAlBlkSiz);
  397.   d_storel(&ptr, mdb->drClpSiz);
  398.   d_storew(&ptr, mdb->drAlBlSt);
  399.   d_storel(&ptr, mdb->drNxtCNID);
  400.   d_storew(&ptr, mdb->drFreeBks);
  401.   d_stores(&ptr, mdb->drVN, sizeof(mdb->drVN));
  402.  
  403.   if (ptr - b != 64)
  404.     abort();
  405.  
  406.   d_storel(&ptr, mdb->drVolBkUp);
  407.   d_storew(&ptr, mdb->drVSeqNum);
  408.   d_storel(&ptr, mdb->drWrCnt);
  409.   d_storel(&ptr, mdb->drXTClpSiz);
  410.   d_storel(&ptr, mdb->drCTClpSiz);
  411.   d_storew(&ptr, mdb->drNmRtDirs);
  412.   d_storel(&ptr, mdb->drFilCnt);
  413.   d_storel(&ptr, mdb->drDirCnt);
  414.  
  415.   for (i = 0; i < 8; ++i)
  416.     d_storel(&ptr, mdb->drFndrInfo[i]);
  417.  
  418.   if (ptr - b != 124)
  419.     abort();
  420.  
  421.   d_storew(&ptr, mdb->drVCSize);
  422.   d_storew(&ptr, mdb->drVBMCSize);
  423.   d_storew(&ptr, mdb->drCtlCSize);
  424.   d_storel(&ptr, mdb->drXTFlSize);
  425.  
  426.   for (i = 0; i < 3; ++i)
  427.     {
  428.       d_storew(&ptr, mdb->drXTExtRec[i].xdrStABN);
  429.       d_storew(&ptr, mdb->drXTExtRec[i].xdrNumABlks);
  430.     }
  431.  
  432.   if (ptr - b != 146)
  433.     abort();
  434.  
  435.   d_storel(&ptr, mdb->drCTFlSize);
  436.  
  437.   for (i = 0; i < 3; ++i)
  438.     {
  439.       d_storew(&ptr, mdb->drCTExtRec[i].xdrStABN);
  440.       d_storew(&ptr, mdb->drCTExtRec[i].xdrNumABlks);
  441.     }
  442.  
  443.   if (ptr - b != 162)
  444.     abort();
  445.  
  446.   if (b_writelb(vol, 2, &b) < 0)
  447.     return -1;
  448.   if (vol->flags & HFS_UPDATE_ALTMDB)
  449.     {
  450. #ifdef APPLE_HYB
  451.       /* "write" alternative MDB to memory copy */
  452.       memcpy(vol->hce->hfs_alt_mdb, &b, sizeof(b));
  453. #else
  454.       if (b_writelb(vol, vol->vlen - 2, &b) < 0)
  455.     return -1;
  456. #endif /* APPLE_HYB */
  457.     }
  458.   vol->flags &= ~(HFS_UPDATE_MDB | HFS_UPDATE_ALTMDB);
  459.  
  460.   return 0;
  461. }
  462.  
  463. /*
  464.  * NAME:    low->readvbm()
  465.  * DESCRIPTION:    read the volume bit map into memory
  466.  */
  467. int l_readvbm(vol)
  468.     hfsvol    *vol;
  469. {
  470.   int vbmst = vol->mdb.drVBMSt;
  471.   int vbmsz = (vol->mdb.drNmAlBlks + 4095) / 4096;
  472.   block *bp;
  473.  
  474.   if (vol->mdb.drAlBlSt - vbmst < vbmsz)
  475.     {
  476.       ERROR(EIO, "volume bitmap collides with volume data");
  477.       return -1;
  478.     }
  479.  
  480.   bp = ALLOC(block, vbmsz);
  481.   if (bp == 0)
  482.     {
  483.       ERROR(ENOMEM, 0);
  484.       return -1;
  485.     }
  486.  
  487.   vol->vbm = bp;
  488.  
  489.   while (vbmsz--)
  490.     {
  491.       if (b_readlb(vol, vbmst++, bp++) < 0)
  492.     {
  493.       FREE(vol->vbm);
  494.       vol->vbm = 0;
  495.  
  496.       return -1;
  497.     }
  498.     }
  499.  
  500.   return 0;
  501. }
  502.  
  503. /*
  504.  * NAME:    low->writevbm()
  505.  * DESCRIPTION:    write the volume bit map to disk
  506.  */
  507. int l_writevbm(vol)
  508.     hfsvol    *vol;
  509. {
  510.   int vbmst = vol->mdb.drVBMSt;
  511.   int vbmsz = (vol->mdb.drNmAlBlks + 4095) / 4096;
  512.   block *bp = vol->vbm;
  513.  
  514.   while (vbmsz--)
  515.     {
  516.       if (b_writelb(vol, vbmst++, bp++) < 0)
  517.     return -1;
  518.     }
  519.  
  520.   vol->flags &= ~HFS_UPDATE_VBM;
  521.  
  522.   return 0;
  523. }
  524.